package com.jddup.program.etm.postgresql;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.jddup.common.annotations.PK;
import com.jddup.common.pojo.TableColumn;
import com.jddup.program.etm.FieldToTableColumnConvertor;
import com.jddup.program.utils.Misc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.persistence.Column;
import javax.persistence.Id;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Map;

/**
 * Created by ZZB on 2017/12/4.
 */
public class PostgresqlFieldToTableColumnConvertor implements FieldToTableColumnConvertor {
    private static final Logger logger = LoggerFactory.getLogger(PostgresqlFieldToTableColumnConvertor.class);

    @Override
    public TableColumn convertFromField(Field declaredField) {
        TableColumn tableColumn = new TableColumn();
        String columnName = null;
        try {
            if (Class.forName("javax.persistence.Column") != null) {
                Column columnAnnotation = declaredField.getAnnotation(Column.class);
                columnName = columnAnnotation.name();
            }
        } catch (Throwable e) {
            //
        }
        try {
            if (Class.forName("com.baomidou.mybatisplus.annotation.TableField") != null) {
                TableField tableField = declaredField.getAnnotation(TableField.class);
                columnName = tableField.value();
            }
        } catch (Throwable e) {
            //
        }

        if (columnName == null) {
            columnName = Misc.camelToUnderline(declaredField.getName());
        }
        tableColumn.setColumnName(columnName);
        tableColumn.setPropertyName(declaredField.getName());
        tableColumn.setPropertyType(declaredField.getType());

        Class clazz = declaredField.getType();
        if (clazz.equals(String.class)) {
            tableColumn.setColumnType("VARCHAR");
            tableColumn.setMaxLength(255L);
        } else if (clazz.equals(Integer.class) || clazz.equals(int.class)) {
            tableColumn.setColumnType("INT4");
        } else if (clazz.equals(Long.class) || clazz.equals(long.class)) {
            tableColumn.setColumnType("INT8");
        } else if (clazz.equals(Float.class) || clazz.equals(float.class)) {
            tableColumn.setColumnType("FLOAT4");
        } else if (clazz.equals(Double.class) || clazz.equals(double.class)) {
            tableColumn.setColumnType("FLOAT8");
        } else if (clazz.equals(Boolean.class) || clazz.equals(boolean.class)) {
            tableColumn.setColumnType("BOOL");
        } else if (clazz.equals(Boolean[].class) || clazz.equals(boolean[].class)) {
            tableColumn.setColumnType("VARBIT");
            tableColumn.setMaxLength(255L);
        } else if (clazz.equals(Byte[].class) || clazz.equals(byte[].class) ||
                clazz.equals(Byte.class) || clazz.equals(byte.class)) {
            tableColumn.setColumnType("BYTEA");
        } else if (clazz.equals(BigDecimal.class)) {
            tableColumn.setColumnType("NUMERIC");
            tableColumn.setPrecision(20L);
            tableColumn.setScale(4L);
        } else if (clazz.equals(BigInteger.class)) {
            tableColumn.setColumnType("NUMERIC");
            tableColumn.setPrecision(20L);
            tableColumn.setScale(0L);
        } else if (clazz.equals(java.sql.Time.class) || clazz.equals(java.time.LocalTime.class)) {
            tableColumn.setColumnType("TIME");
        } else if (clazz.equals(java.sql.Date.class) || clazz.equals(java.time.LocalDate.class)) {
            tableColumn.setColumnType("DATE");
        } else if (clazz.equals(java.util.Date.class) || clazz.equals(java.time.LocalDateTime.class)) {
            tableColumn.setColumnType("TIMESTAMP");
        } else if (clazz.equals(Map.class)) {
            tableColumn.setColumnType("JSON");
        } else {
            logger.error("不支持的数据类型！field[{}],type[{}]", declaredField.getName(), clazz.getName());
        }

        boolean isPrimaryKey = false;
        try {
            if (Class.forName("javax.persistence.Id") != null) {
                Id idAnn = declaredField.getAnnotation(Id.class);
                if (idAnn != null)
                    isPrimaryKey = true;
            }
        } catch (Throwable e) {
            //
        }

        try {
            if (Class.forName("com.baomidou.mybatisplus.annotation.TableId") != null) {
                TableId tableId = declaredField.getAnnotation(TableId.class);
                if (tableId != null)
                    isPrimaryKey = true;
            }
        } catch (Throwable e) {
            //
        }
        try {
            if (Class.forName("com.jddup.common.annotations.PK") != null) {
                PK pk = declaredField.getAnnotation(PK.class);
                if (pk != null)
                    isPrimaryKey = true;
            }
        } catch (Throwable e) {
            //
        }
        tableColumn.setPrimaryKey(isPrimaryKey);
        return tableColumn;
    }

    @Override
    public void buildFullType(TableColumn tableColumn) {
        String typeName = tableColumn.getColumnType();
        Long maxLength = tableColumn.getMaxLength();
        Long precision = tableColumn.getPrecision();
        Long scale = tableColumn.getScale();
        if (typeName == null) {
            logger.error("typeName == null!");
        }
        if ("CHAR".equals(typeName.toUpperCase()) ||
                "VARCHAR".equals(typeName.toUpperCase()) ||
                "VARBIT".equals(typeName.toUpperCase())) {

            if (maxLength != null && maxLength != 0) {
                typeName = typeName + "(" + maxLength + ")";
            }
        }
        if ("NUMERIC".equals(typeName.toUpperCase())) {
            if (precision != null && precision != 0) {
                typeName = typeName + "(" + precision + "," + scale + ")";
            }
        }
        if (("FLOAT4".equals(typeName.toUpperCase()) ||
                "FLOAT8".equals(typeName.toUpperCase()))) {
            if (precision != null && precision != 0) {
                typeName = typeName + "(" + precision + "," + scale + ")";
            } else if (precision != null) {
                typeName = typeName + "(" + precision + ")";
            }
        }
        tableColumn.setTypeFullName(typeName);
    }
}
